
#include "update.h"
#include "eeprom.h"
static const unsigned char aucCRCHi[] = {
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40};

static const unsigned char aucCRCLo[] = {
    0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7,
    0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E,
    0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9,
    0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC,
    0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
    0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32,
    0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D,
    0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38,
    0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF,
    0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
    0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1,
    0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4,
    0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB,
    0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA,
    0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
    0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0,
    0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97,
    0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E,
    0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89,
    0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
    0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83,
    0x41, 0x81, 0x80, 0x40};

unsigned char VersionChar[15] = "RB2303V1.011234";
unsigned char rsRxBuf[MAXU2MAX];
unsigned int rsRxLen = 0;
unsigned int rsRxTime = 0;
unsigned int rsRxIndex = 0;
unsigned char rsPackFlag = 0;
unsigned short part_num;             // 包数  如果这个值是4000表示 这个bin文件有500Kbytes： 4000x128=500Kbytes
unsigned short part_index;           // 包序号
unsigned short part_curIndexLen = 0; // 当前包长度  >=128

unsigned short CRC16x(unsigned char *pucFrame, unsigned short usLen)
{
    unsigned char ucCRCHi = 0xFF;
    unsigned char ucCRCLo = 0xFF;
    int iIndex;
    while (usLen--)
    {
        iIndex = ucCRCLo ^ *(pucFrame++);
        ucCRCLo = (unsigned char)(ucCRCHi ^ aucCRCHi[iIndex]);
        ucCRCHi = aucCRCLo[iIndex];
    }
    return (unsigned short)(ucCRCHi << 8 | ucCRCLo);
}
void appendCrcLH(unsigned char *ahead, unsigned short lens)
{
    unsigned short crc16tmpd = CRC16x(ahead, lens);
    *(ahead + lens + 0) = (crc16tmpd & 0x00ff) >> 0;
    *(ahead + lens + 1) = (crc16tmpd & 0xff00) >> 8;
}

unsigned char checkPackPro(unsigned char *rdata, unsigned short rlen)
{
    unsigned short pack_len = 0;
    unsigned short pack_crcLH0;
    unsigned short pack_crcLH1;
    unsigned int WriteAddress = 0;
    unsigned short writeLen = 0;
    pack_len = *(unsigned short *)&rdata[8];     // 长度校验
    if (pack_len > 528 || rlen != pack_len + 16) // 512+16=528
    {
        return 2; // 长度校验不通过
    }
    if (
        rdata[pack_len + 12] != 0xAB ||
        rdata[pack_len + 13] != 0xBC ||
        rdata[pack_len + 14] != 0xCD ||
        rdata[pack_len + 15] != 0xDE) // 结尾校验不通过
    {
        return 3; // 结尾校验不通过
    }
    pack_crcLH0 = *(unsigned short *)&rdata[pack_len + 10];
    pack_crcLH1 = CRC16x(rdata + 4, pack_len + 6);
    if (pack_crcLH0 != pack_crcLH1)
    {
        return 4; // 内容CRC校验不通过
    }
    else // 校验通过写入FLASH
    {
        part_num = *(unsigned short *)&rdata[4];         // 被拆分包的个数
        part_index = *(unsigned short *)&rdata[6];       // 包的序号
        part_curIndexLen = *(unsigned short *)&rdata[8]; // 当前序号包内容的字节数

        if (part_index == 0) // 第0个包擦除APP
        {
            FLASH_If_Init();              // 解锁
            while (FLASH_If_Erase() != 0) // 擦除
            {
                delay_ms(1);
            }
        }

        WriteAddress = 0x08010000 + (512 * part_index);                     // 写入地址
        writeLen = (part_curIndexLen) / 4 + (((part_curIndexLen) % 4) > 0); // 写入多少个4字节
        while (FLASH_If_Write(&WriteAddress, (uint32_t *)&rdata[10], writeLen) != 0)
        {
            delay_ms(1);
        }
        unsigned int why = EE_ReadWord(WriteAddress);
        if (part_num == part_index + 1) // 最后一包
        {
            FLASH_If_UnInit();  // 最后一包给FLASH上锁
            bootloaderflag = 3; // 升级完成
        }
        return 1;
    }
    return 0;
}
// 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17
// A0 A1 A2 11 A0 A1 A2 A3      在bootloader中退出bootloader尝试进入app
// AA BB CC 11 AA BB CC DD      在app中重启再次进入bootloader后尝试升级
// AA BB CC 21 P_NUM P_IND P_LEN [128] C0 C1 AB BC CD DE      下发升级包  其中C0 和 C1 表示校验
// AA BB CC 21 P_NUM P_IND P_LEN C0 C1 AB BC CD DE            升级包应答  其中C0 和 C1 表示校验
// 升级包信息之P_NUM ：包的个数
// 升级包信息之P_IND ：这个数据包的内容
// 升级包信息之P_LEN ：这个数据包的长度
// 在上位机端收到的应答中升级包信息下发和应答一致则表示这个包已经成功写入设备Flash，上位机可以选择下发下一个数据包
// 在上位机端收到的应答中升级包信息下发和应答不一致的情况表示设备端校验出错，上位机端可以选择重传
// 在设备端 收P_IND为零的包时设备将会擦除APP所在flash扇区，
// 在设备端收到的最后一个数据包时（P_NUM=P_IND+1）设备端会给flash上锁退出bootloader尝试进入app
void exPool(void)
{
    if (rsPackFlag == 1 && rsRxTime > 30) // 断包 防止有些上位机软件发送数据不连续
    {
        rsPackFlag = 0;
        rsRxTime = 0;
        rsRxLen = rsRxIndex;
        rsRxIndex = 0;
        if ( // 进入boot   重启
            rsRxLen >= 14 &&
            rsRxBuf[0] == 0xAA &&
            rsRxBuf[1] == 0xBB &&
            rsRxBuf[2] == 0xCC &&
            rsRxBuf[3] == 0x011 &&
            rsRxBuf[14] == 0xAA &&
            rsRxBuf[15] == 0xBB &&
            rsRxBuf[16] == 0xCC &&
            rsRxBuf[17] == 0xDD)
        {
            memcpy(VersionChar, &rsRxBuf[4], 15);
            memcpy(&TxBufU2[0], &rsRxBuf[0], 18);
            HAL_UART_Transmit(&huart2, TxBufU2, 19, 20);
            __set_FAULTMASK(1); // 关闭所有中断
            NVIC_SystemReset(); // 复位
        }
        else if ( // 读取版本号
            rsRxLen >= 14 &&
            rsRxBuf[0] == 0xDD &&
            rsRxBuf[1] == 0xCC &&
            rsRxBuf[2] == 0xBB &&
            rsRxBuf[3] == 0x11)
        {
            memcpy(&TxBufU2[0], &rsRxBuf[0], 15);
            memcpy(&TxBufU2[4], VersionChar, 15);
            HAL_UART_Transmit(&huart2, TxBufU2, 19, 500);
        }
        else if (
            rsRxLen >= 16 &&
            rsRxBuf[0] == 0xAA &&
            rsRxBuf[1] == 0xBB &&
            rsRxBuf[2] == 0xCC &&
            rsRxBuf[3] == 0x21) // 升级包
        {

            unsigned short i;
            unsigned short rlen;
            i = 0;
            unsigned char retuc = checkPackPro(rsRxBuf, rsRxLen); // 保证数据正确再写入

            if (retuc == 1) // 校验通过 校验通过写入flash
            {
                rlen = part_curIndexLen; // rsRxBuf[8] rsRxBuf[9]
            }
            else
            {
                rlen = 0;
            }
            TxBufU2[i++] = 0xAA;
            TxBufU2[i++] = 0xBB;
            TxBufU2[i++] = 0xCC;
            TxBufU2[i++] = 0x21;
            TxBufU2[i++] = part_num >> 0;
            TxBufU2[i++] = part_num >> 8;
            TxBufU2[i++] = part_index >> 0;
            TxBufU2[i++] = part_index >> 8;
            TxBufU2[i++] = rlen >> 0;
            TxBufU2[i++] = rlen >> 8;
            appendCrcLH(TxBufU2 + 4, i - 4);
            i++;
            i++;
            TxBufU2[i++] = 0xAB;
            TxBufU2[i++] = 0xBC;
            TxBufU2[i++] = 0xCD;
            TxBufU2[i++] = 0xDE;

            HAL_UART_Transmit(&huart2, TxBufU2, i, 20);
        }
        HAL_UART_Receive_DMA(&huart2, RxBufU2, MAXU2MAX); // 再次开启DMA接收
    }
}